home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Resources / Chat & Communication / Digsby build 37 / digsby_setup.exe / lib / cookielib.pyo (.txt) < prev    next >
Encoding:
Python Compiled Bytecode  |  2008-10-13  |  38.6 KB  |  1,462 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyo (Python 2.5)
  3.  
  4. __all__ = [
  5.     'Cookie',
  6.     'CookieJar',
  7.     'CookiePolicy',
  8.     'DefaultCookiePolicy',
  9.     'FileCookieJar',
  10.     'LWPCookieJar',
  11.     'LoadError',
  12.     'MozillaCookieJar']
  13. import re
  14. import urlparse
  15. import copy
  16. import time
  17. import urllib
  18.  
  19. try:
  20.     import threading as _threading
  21. except ImportError:
  22.     import dummy_threading as _threading
  23.  
  24. import httplib
  25. from calendar import timegm
  26. debug = False
  27. logger = None
  28.  
  29. def _debug(*args):
  30.     global logger
  31.     if not debug:
  32.         return None
  33.     
  34.     if not logger:
  35.         import logging
  36.         logger = logging.getLogger('cookielib')
  37.     
  38.     return logger.debug(*args)
  39.  
  40. DEFAULT_HTTP_PORT = str(httplib.HTTP_PORT)
  41. MISSING_FILENAME_TEXT = 'a filename was not supplied (nor was the CookieJar instance initialised with one)'
  42.  
  43. def _warn_unhandled_exception():
  44.     import warnings
  45.     import traceback
  46.     import StringIO
  47.     f = StringIO.StringIO()
  48.     traceback.print_exc(None, f)
  49.     msg = f.getvalue()
  50.     warnings.warn('cookielib bug!\n%s' % msg, stacklevel = 2)
  51.  
  52. EPOCH_YEAR = 1970
  53.  
  54. def _timegm(tt):
  55.     (year, month, mday, hour, min, sec) = tt[:6]
  56.     if year >= EPOCH_YEAR:
  57.         if month <= month:
  58.             pass
  59.         elif month <= 12:
  60.             if mday <= mday:
  61.                 pass
  62.             elif mday <= 31:
  63.                 if hour <= hour:
  64.                     pass
  65.                 elif hour <= 24:
  66.                     if min <= min:
  67.                         pass
  68.                     elif min <= 59:
  69.                         if sec <= sec:
  70.                             pass
  71.                         elif sec <= 61:
  72.                             return timegm(tt)
  73.                         else:
  74.                             return None
  75.  
  76. DAYS = [
  77.     'Mon',
  78.     'Tue',
  79.     'Wed',
  80.     'Thu',
  81.     'Fri',
  82.     'Sat',
  83.     'Sun']
  84. MONTHS = [
  85.     'Jan',
  86.     'Feb',
  87.     'Mar',
  88.     'Apr',
  89.     'May',
  90.     'Jun',
  91.     'Jul',
  92.     'Aug',
  93.     'Sep',
  94.     'Oct',
  95.     'Nov',
  96.     'Dec']
  97. MONTHS_LOWER = []
  98. for month in MONTHS:
  99.     MONTHS_LOWER.append(month.lower())
  100.  
  101.  
  102. def time2isoz(t = None):
  103.     if t is None:
  104.         t = time.time()
  105.     
  106.     (year, mon, mday, hour, min, sec) = time.gmtime(t)[:6]
  107.     return '%04d-%02d-%02d %02d:%02d:%02dZ' % (year, mon, mday, hour, min, sec)
  108.  
  109.  
  110. def time2netscape(t = None):
  111.     if t is None:
  112.         t = time.time()
  113.     
  114.     (year, mon, mday, hour, min, sec, wday) = time.gmtime(t)[:7]
  115.     return '%s %02d-%s-%04d %02d:%02d:%02d GMT' % (DAYS[wday], mday, MONTHS[mon - 1], year, hour, min, sec)
  116.  
  117. UTC_ZONES = {
  118.     'GMT': None,
  119.     'UTC': None,
  120.     'UT': None,
  121.     'Z': None }
  122. TIMEZONE_RE = re.compile('^([-+])?(\\d\\d?):?(\\d\\d)?$')
  123.  
  124. def offset_from_tz_string(tz):
  125.     offset = None
  126.     if tz in UTC_ZONES:
  127.         offset = 0
  128.     else:
  129.         m = TIMEZONE_RE.search(tz)
  130.         if m:
  131.             offset = 3600 * int(m.group(2))
  132.             if m.group(3):
  133.                 offset = offset + 60 * int(m.group(3))
  134.             
  135.             if m.group(1) == '-':
  136.                 offset = -offset
  137.             
  138.         
  139.     return offset
  140.  
  141.  
  142. def _str2time(day, mon, yr, hr, min, sec, tz):
  143.     
  144.     try:
  145.         mon = MONTHS_LOWER.index(mon.lower()) + 1
  146.     except ValueError:
  147.         
  148.         try:
  149.             imon = int(mon)
  150.         except ValueError:
  151.             return None
  152.  
  153.         if imon <= imon:
  154.             pass
  155.         elif imon <= 12:
  156.             mon = imon
  157.         else:
  158.             return None
  159.     except:
  160.         1
  161.  
  162.     if hr is None:
  163.         hr = 0
  164.     
  165.     if min is None:
  166.         min = 0
  167.     
  168.     if sec is None:
  169.         sec = 0
  170.     
  171.     yr = int(yr)
  172.     day = int(day)
  173.     hr = int(hr)
  174.     min = int(min)
  175.     sec = int(sec)
  176.     if yr < 1000:
  177.         cur_yr = time.localtime(time.time())[0]
  178.         m = cur_yr % 100
  179.         tmp = yr
  180.         yr = yr + cur_yr - m
  181.         m = m - tmp
  182.         if abs(m) > 50:
  183.             if m > 0:
  184.                 yr = yr + 100
  185.             else:
  186.                 yr = yr - 100
  187.         
  188.     
  189.     t = _timegm((yr, mon, day, hr, min, sec, tz))
  190.     if t is not None:
  191.         if tz is None:
  192.             tz = 'UTC'
  193.         
  194.         tz = tz.upper()
  195.         offset = offset_from_tz_string(tz)
  196.         if offset is None:
  197.             return None
  198.         
  199.         t = t - offset
  200.     
  201.     return t
  202.  
  203. STRICT_DATE_RE = re.compile('^[SMTWF][a-z][a-z], (\\d\\d) ([JFMASOND][a-z][a-z]) (\\d\\d\\d\\d) (\\d\\d):(\\d\\d):(\\d\\d) GMT$')
  204. WEEKDAY_RE = re.compile('^(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)[a-z]*,?\\s*', re.I)
  205. LOOSE_HTTP_DATE_RE = re.compile('^\n    (\\d\\d?)            # day\n       (?:\\s+|[-\\/])\n    (\\w+)              # month\n        (?:\\s+|[-\\/])\n    (\\d+)              # year\n    (?:\n          (?:\\s+|:)    # separator before clock\n       (\\d\\d?):(\\d\\d)  # hour:min\n       (?::(\\d\\d))?    # optional seconds\n    )?                 # optional clock\n       \\s*\n    ([-+]?\\d{2,4}|(?![APap][Mm]\\b)[A-Za-z]+)? # timezone\n       \\s*\n    (?:\\(\\w+\\))?       # ASCII representation of timezone in parens.\n       \\s*$', re.X)
  206.  
  207. def http2time(text):
  208.     m = STRICT_DATE_RE.search(text)
  209.     if m:
  210.         g = m.groups()
  211.         mon = MONTHS_LOWER.index(g[1].lower()) + 1
  212.         tt = (int(g[2]), mon, int(g[0]), int(g[3]), int(g[4]), float(g[5]))
  213.         return _timegm(tt)
  214.     
  215.     text = text.lstrip()
  216.     text = WEEKDAY_RE.sub('', text, 1)
  217.     (day, mon, yr, hr, min, sec, tz) = [
  218.         None] * 7
  219.     m = LOOSE_HTTP_DATE_RE.search(text)
  220.     if m is not None:
  221.         (day, mon, yr, hr, min, sec, tz) = m.groups()
  222.     else:
  223.         return None
  224.     return _str2time(day, mon, yr, hr, min, sec, tz)
  225.  
  226. ISO_DATE_RE = re.compile('^\n    (\\d{4})              # year\n       [-\\/]?\n    (\\d\\d?)              # numerical month\n       [-\\/]?\n    (\\d\\d?)              # day\n   (?:\n         (?:\\s+|[-:Tt])  # separator before clock\n      (\\d\\d?):?(\\d\\d)    # hour:min\n      (?::?(\\d\\d(?:\\.\\d*)?))?  # optional seconds (and fractional)\n   )?                    # optional clock\n      \\s*\n   ([-+]?\\d\\d?:?(:?\\d\\d)?\n    |Z|z)?               # timezone  (Z is "zero meridian", i.e. GMT)\n      \\s*$', re.X)
  227.  
  228. def iso2time(text):
  229.     text = text.lstrip()
  230.     (day, mon, yr, hr, min, sec, tz) = [
  231.         None] * 7
  232.     m = ISO_DATE_RE.search(text)
  233.     if m is not None:
  234.         (yr, mon, day, hr, min, sec, tz, _) = m.groups()
  235.     else:
  236.         return None
  237.     return _str2time(day, mon, yr, hr, min, sec, tz)
  238.  
  239.  
  240. def unmatched(match):
  241.     (start, end) = match.span(0)
  242.     return match.string[:start] + match.string[end:]
  243.  
  244. HEADER_TOKEN_RE = re.compile('^\\s*([^=\\s;,]+)')
  245. HEADER_QUOTED_VALUE_RE = re.compile('^\\s*=\\s*\\"([^\\"\\\\]*(?:\\\\.[^\\"\\\\]*)*)\\"')
  246. HEADER_VALUE_RE = re.compile('^\\s*=\\s*([^\\s;,]*)')
  247. HEADER_ESCAPE_RE = re.compile('\\\\(.)')
  248.  
  249. def split_header_words(header_values):
  250.     result = []
  251.     for text in header_values:
  252.         orig_text = text
  253.         pairs = []
  254.         while text:
  255.             m = HEADER_TOKEN_RE.search(text)
  256.             if m:
  257.                 text = unmatched(m)
  258.                 name = m.group(1)
  259.                 m = HEADER_QUOTED_VALUE_RE.search(text)
  260.                 if m:
  261.                     text = unmatched(m)
  262.                     value = m.group(1)
  263.                     value = HEADER_ESCAPE_RE.sub('\\1', value)
  264.                 else:
  265.                     m = HEADER_VALUE_RE.search(text)
  266.                     if m:
  267.                         text = unmatched(m)
  268.                         value = m.group(1)
  269.                         value = value.rstrip()
  270.                     else:
  271.                         value = None
  272.                 pairs.append((name, value))
  273.                 continue
  274.             if text.lstrip().startswith(','):
  275.                 text = text.lstrip()[1:]
  276.                 if pairs:
  277.                     result.append(pairs)
  278.                 
  279.                 pairs = []
  280.                 continue
  281.             (non_junk, nr_junk_chars) = re.subn('^[=\\s;]*', '', text)
  282.             text = non_junk
  283.         if pairs:
  284.             result.append(pairs)
  285.             continue
  286.     
  287.     return result
  288.  
  289. HEADER_JOIN_ESCAPE_RE = re.compile('([\\"\\\\])')
  290.  
  291. def join_header_words(lists):
  292.     headers = []
  293.     for pairs in lists:
  294.         attr = []
  295.         for k, v in pairs:
  296.             if v is not None:
  297.                 if not re.search('^\\w+$', v):
  298.                     v = HEADER_JOIN_ESCAPE_RE.sub('\\\\\\1', v)
  299.                     v = '"%s"' % v
  300.                 
  301.                 k = '%s=%s' % (k, v)
  302.             
  303.             attr.append(k)
  304.         
  305.         if attr:
  306.             headers.append('; '.join(attr))
  307.             continue
  308.     
  309.     return ', '.join(headers)
  310.  
  311.  
  312. def parse_ns_headers(ns_headers):
  313.     known_attrs = ('expires', 'domain', 'path', 'secure', 'port', 'max-age')
  314.     result = []
  315.     for ns_header in ns_headers:
  316.         pairs = []
  317.         version_set = False
  318.         for ii, param in enumerate(re.split(';\\s*', ns_header)):
  319.             param = param.rstrip()
  320.             if param == '':
  321.                 continue
  322.             
  323.             if '=' not in param:
  324.                 k = param
  325.                 v = None
  326.             else:
  327.                 (k, v) = re.split('\\s*=\\s*', param, 1)
  328.                 k = k.lstrip()
  329.             if ii != 0:
  330.                 lc = k.lower()
  331.                 if lc in known_attrs:
  332.                     k = lc
  333.                 
  334.                 if k == 'version':
  335.                     version_set = True
  336.                 
  337.                 if k == 'expires':
  338.                     if v.startswith('"'):
  339.                         v = v[1:]
  340.                     
  341.                     if v.endswith('"'):
  342.                         v = v[:-1]
  343.                     
  344.                     v = http2time(v)
  345.                 
  346.             
  347.             pairs.append((k, v))
  348.         
  349.         if pairs:
  350.             if not version_set:
  351.                 pairs.append(('version', '0'))
  352.             
  353.             result.append(pairs)
  354.             continue
  355.     
  356.     return result
  357.  
  358. IPV4_RE = re.compile('\\.\\d+$')
  359.  
  360. def is_HDN(text):
  361.     if IPV4_RE.search(text):
  362.         return False
  363.     
  364.     if text == '':
  365.         return False
  366.     
  367.     if text[0] == '.' or text[-1] == '.':
  368.         return False
  369.     
  370.     return True
  371.  
  372.  
  373. def domain_match(A, B):
  374.     A = A.lower()
  375.     B = B.lower()
  376.     if A == B:
  377.         return True
  378.     
  379.     if not is_HDN(A):
  380.         return False
  381.     
  382.     i = A.rfind(B)
  383.     if i == -1 or i == 0:
  384.         return False
  385.     
  386.     if not B.startswith('.'):
  387.         return False
  388.     
  389.     if not is_HDN(B[1:]):
  390.         return False
  391.     
  392.     return True
  393.  
  394.  
  395. def liberal_is_HDN(text):
  396.     if IPV4_RE.search(text):
  397.         return False
  398.     
  399.     return True
  400.  
  401.  
  402. def user_domain_match(A, B):
  403.     A = A.lower()
  404.     B = B.lower()
  405.     if not liberal_is_HDN(A) and liberal_is_HDN(B):
  406.         if A == B:
  407.             return True
  408.         
  409.         return False
  410.     
  411.     initial_dot = B.startswith('.')
  412.     if initial_dot and A.endswith(B):
  413.         return True
  414.     
  415.     if not initial_dot and A == B:
  416.         return True
  417.     
  418.     return False
  419.  
  420. cut_port_re = re.compile(':\\d+$')
  421.  
  422. def request_host(request):
  423.     url = request.get_full_url()
  424.     host = urlparse.urlparse(url)[1]
  425.     if host == '':
  426.         host = request.get_header('Host', '')
  427.     
  428.     host = cut_port_re.sub('', host, 1)
  429.     return host.lower()
  430.  
  431.  
  432. def eff_request_host(request):
  433.     erhn = req_host = request_host(request)
  434.     if req_host.find('.') == -1 and not IPV4_RE.search(req_host):
  435.         erhn = req_host + '.local'
  436.     
  437.     return (req_host, erhn)
  438.  
  439.  
  440. def request_path(request):
  441.     url = request.get_full_url()
  442.     (path, parameters, query, frag) = urlparse.urlparse(url)[2:]
  443.     if parameters:
  444.         path = '%s;%s' % (path, parameters)
  445.     
  446.     path = escape_path(path)
  447.     req_path = urlparse.urlunparse(('', '', path, '', query, frag))
  448.     if not req_path.startswith('/'):
  449.         req_path = '/' + req_path
  450.     
  451.     return req_path
  452.  
  453.  
  454. def request_port(request):
  455.     host = request.get_host()
  456.     i = host.find(':')
  457.     if i >= 0:
  458.         port = host[i + 1:]
  459.         
  460.         try:
  461.             int(port)
  462.         except ValueError:
  463.             _debug("nonnumeric port: '%s'", port)
  464.             return None
  465.         except:
  466.             None<EXCEPTION MATCH>ValueError
  467.         
  468.  
  469.     None<EXCEPTION MATCH>ValueError
  470.     port = DEFAULT_HTTP_PORT
  471.     return port
  472.  
  473. HTTP_PATH_SAFE = "%/;:@&=+$,!~*'()"
  474. ESCAPED_CHAR_RE = re.compile('%([0-9a-fA-F][0-9a-fA-F])')
  475.  
  476. def uppercase_escaped_char(match):
  477.     return '%%%s' % match.group(1).upper()
  478.  
  479.  
  480. def escape_path(path):
  481.     if isinstance(path, unicode):
  482.         path = path.encode('utf-8')
  483.     
  484.     path = urllib.quote(path, HTTP_PATH_SAFE)
  485.     path = ESCAPED_CHAR_RE.sub(uppercase_escaped_char, path)
  486.     return path
  487.  
  488.  
  489. def reach(h):
  490.     i = h.find('.')
  491.     if i >= 0:
  492.         b = h[i + 1:]
  493.         i = b.find('.')
  494.         if is_HDN(h):
  495.             pass
  496.         None if i >= 0 or b == 'local' else b == 'local'
  497.     
  498.     return h
  499.  
  500.  
  501. def is_third_party(request):
  502.     req_host = request_host(request)
  503.     if not domain_match(req_host, reach(request.get_origin_req_host())):
  504.         return True
  505.     else:
  506.         return False
  507.  
  508.  
  509. class Cookie:
  510.     
  511.     def __init__(self, version, name, value, port, port_specified, domain, domain_specified, domain_initial_dot, path, path_specified, secure, expires, discard, comment, comment_url, rest, rfc2109 = False):
  512.         if version is not None:
  513.             version = int(version)
  514.         
  515.         if expires is not None:
  516.             expires = int(expires)
  517.         
  518.         if port is None and port_specified is True:
  519.             raise ValueError('if port is None, port_specified must be false')
  520.         
  521.         self.version = version
  522.         self.name = name
  523.         self.value = value
  524.         self.port = port
  525.         self.port_specified = port_specified
  526.         self.domain = domain.lower()
  527.         self.domain_specified = domain_specified
  528.         self.domain_initial_dot = domain_initial_dot
  529.         self.path = path
  530.         self.path_specified = path_specified
  531.         self.secure = secure
  532.         self.expires = expires
  533.         self.discard = discard
  534.         self.comment = comment
  535.         self.comment_url = comment_url
  536.         self.rfc2109 = rfc2109
  537.         self._rest = copy.copy(rest)
  538.  
  539.     
  540.     def has_nonstandard_attr(self, name):
  541.         return name in self._rest
  542.  
  543.     
  544.     def get_nonstandard_attr(self, name, default = None):
  545.         return self._rest.get(name, default)
  546.  
  547.     
  548.     def set_nonstandard_attr(self, name, value):
  549.         self._rest[name] = value
  550.  
  551.     
  552.     def is_expired(self, now = None):
  553.         if now is None:
  554.             now = time.time()
  555.         
  556.         if self.expires is not None and self.expires <= now:
  557.             return True
  558.         
  559.         return False
  560.  
  561.     
  562.     def __str__(self):
  563.         if self.port is None:
  564.             p = ''
  565.         else:
  566.             p = ':' + self.port
  567.         limit = self.domain + p + self.path
  568.         if self.value is not None:
  569.             namevalue = '%s=%s' % (self.name, self.value)
  570.         else:
  571.             namevalue = self.name
  572.         return '<Cookie %s for %s>' % (namevalue, limit)
  573.  
  574.     
  575.     def __repr__(self):
  576.         args = []
  577.         for name in ('version', 'name', 'value', 'port', 'port_specified', 'domain', 'domain_specified', 'domain_initial_dot', 'path', 'path_specified', 'secure', 'expires', 'discard', 'comment', 'comment_url'):
  578.             attr = getattr(self, name)
  579.             args.append('%s=%s' % (name, repr(attr)))
  580.         
  581.         args.append('rest=%s' % repr(self._rest))
  582.         args.append('rfc2109=%s' % repr(self.rfc2109))
  583.         return 'Cookie(%s)' % ', '.join(args)
  584.  
  585.  
  586.  
  587. class CookiePolicy:
  588.     
  589.     def set_ok(self, cookie, request):
  590.         raise NotImplementedError()
  591.  
  592.     
  593.     def return_ok(self, cookie, request):
  594.         raise NotImplementedError()
  595.  
  596.     
  597.     def domain_return_ok(self, domain, request):
  598.         return True
  599.  
  600.     
  601.     def path_return_ok(self, path, request):
  602.         return True
  603.  
  604.  
  605.  
  606. class DefaultCookiePolicy(CookiePolicy):
  607.     DomainStrictNoDots = 1
  608.     DomainStrictNonDomain = 2
  609.     DomainRFC2965Match = 4
  610.     DomainLiberal = 0
  611.     DomainStrict = DomainStrictNoDots | DomainStrictNonDomain
  612.     
  613.     def __init__(self, blocked_domains = None, allowed_domains = None, netscape = True, rfc2965 = False, rfc2109_as_netscape = None, hide_cookie2 = False, strict_domain = False, strict_rfc2965_unverifiable = True, strict_ns_unverifiable = False, strict_ns_domain = DomainLiberal, strict_ns_set_initial_dollar = False, strict_ns_set_path = False):
  614.         self.netscape = netscape
  615.         self.rfc2965 = rfc2965
  616.         self.rfc2109_as_netscape = rfc2109_as_netscape
  617.         self.hide_cookie2 = hide_cookie2
  618.         self.strict_domain = strict_domain
  619.         self.strict_rfc2965_unverifiable = strict_rfc2965_unverifiable
  620.         self.strict_ns_unverifiable = strict_ns_unverifiable
  621.         self.strict_ns_domain = strict_ns_domain
  622.         self.strict_ns_set_initial_dollar = strict_ns_set_initial_dollar
  623.         self.strict_ns_set_path = strict_ns_set_path
  624.         if blocked_domains is not None:
  625.             self._blocked_domains = tuple(blocked_domains)
  626.         else:
  627.             self._blocked_domains = ()
  628.         if allowed_domains is not None:
  629.             allowed_domains = tuple(allowed_domains)
  630.         
  631.         self._allowed_domains = allowed_domains
  632.  
  633.     
  634.     def blocked_domains(self):
  635.         return self._blocked_domains
  636.  
  637.     
  638.     def set_blocked_domains(self, blocked_domains):
  639.         self._blocked_domains = tuple(blocked_domains)
  640.  
  641.     
  642.     def is_blocked(self, domain):
  643.         for blocked_domain in self._blocked_domains:
  644.             if user_domain_match(domain, blocked_domain):
  645.                 return True
  646.                 continue
  647.         
  648.         return False
  649.  
  650.     
  651.     def allowed_domains(self):
  652.         return self._allowed_domains
  653.  
  654.     
  655.     def set_allowed_domains(self, allowed_domains):
  656.         if allowed_domains is not None:
  657.             allowed_domains = tuple(allowed_domains)
  658.         
  659.         self._allowed_domains = allowed_domains
  660.  
  661.     
  662.     def is_not_allowed(self, domain):
  663.         if self._allowed_domains is None:
  664.             return False
  665.         
  666.         for allowed_domain in self._allowed_domains:
  667.             if user_domain_match(domain, allowed_domain):
  668.                 return False
  669.                 continue
  670.         
  671.         return True
  672.  
  673.     
  674.     def set_ok(self, cookie, request):
  675.         _debug(' - checking cookie %s=%s', cookie.name, cookie.value)
  676.         for n in ('version', 'verifiability', 'name', 'path', 'domain', 'port'):
  677.             fn_name = 'set_ok_' + n
  678.             fn = getattr(self, fn_name)
  679.             if not fn(cookie, request):
  680.                 return False
  681.                 continue
  682.         
  683.         return True
  684.  
  685.     
  686.     def set_ok_version(self, cookie, request):
  687.         if cookie.version is None:
  688.             _debug('   Set-Cookie2 without version attribute (%s=%s)', cookie.name, cookie.value)
  689.             return False
  690.         
  691.         if cookie.version > 0 and not (self.rfc2965):
  692.             _debug('   RFC 2965 cookies are switched off')
  693.             return False
  694.         elif cookie.version == 0 and not (self.netscape):
  695.             _debug('   Netscape cookies are switched off')
  696.             return False
  697.         
  698.         return True
  699.  
  700.     
  701.     def set_ok_verifiability(self, cookie, request):
  702.         if request.is_unverifiable() and is_third_party(request):
  703.             if cookie.version > 0 and self.strict_rfc2965_unverifiable:
  704.                 _debug('   third-party RFC 2965 cookie during unverifiable transaction')
  705.                 return False
  706.             elif cookie.version == 0 and self.strict_ns_unverifiable:
  707.                 _debug('   third-party Netscape cookie during unverifiable transaction')
  708.                 return False
  709.             
  710.         
  711.         return True
  712.  
  713.     
  714.     def set_ok_name(self, cookie, request):
  715.         if cookie.version == 0 and self.strict_ns_set_initial_dollar and cookie.name.startswith('$'):
  716.             _debug("   illegal name (starts with '$'): '%s'", cookie.name)
  717.             return False
  718.         
  719.         return True
  720.  
  721.     
  722.     def set_ok_path(self, cookie, request):
  723.         if cookie.path_specified:
  724.             req_path = request_path(request)
  725.             if (cookie.version > 0 or cookie.version == 0 or self.strict_ns_set_path) and not req_path.startswith(cookie.path):
  726.                 _debug('   path attribute %s is not a prefix of request path %s', cookie.path, req_path)
  727.                 return False
  728.             
  729.         
  730.         return True
  731.  
  732.     
  733.     def set_ok_domain(self, cookie, request):
  734.         if self.is_blocked(cookie.domain):
  735.             _debug('   domain %s is in user block-list', cookie.domain)
  736.             return False
  737.         
  738.         if self.is_not_allowed(cookie.domain):
  739.             _debug('   domain %s is not in user allow-list', cookie.domain)
  740.             return False
  741.         
  742.         if cookie.domain_specified:
  743.             (req_host, erhn) = eff_request_host(request)
  744.             domain = cookie.domain
  745.             if self.strict_domain and domain.count('.') >= 2:
  746.                 i = domain.rfind('.')
  747.                 j = domain.rfind('.', 0, i)
  748.                 if j == 0:
  749.                     tld = domain[i + 1:]
  750.                     sld = domain[j + 1:i]
  751.                     if sld.lower() in ('co', 'ac', 'com', 'edu', 'org', 'net', 'gov', 'mil', 'int', 'aero', 'biz', 'cat', 'coop', 'info', 'jobs', 'mobi', 'museum', 'name', 'pro', 'travel', 'eu') and len(tld) == 2:
  752.                         _debug('   country-code second level domain %s', domain)
  753.                         return False
  754.                     
  755.                 
  756.             
  757.             if domain.startswith('.'):
  758.                 undotted_domain = domain[1:]
  759.             else:
  760.                 undotted_domain = domain
  761.             embedded_dots = undotted_domain.find('.') >= 0
  762.             if not embedded_dots and domain != '.local':
  763.                 _debug('   non-local domain %s contains no embedded dot', domain)
  764.                 return False
  765.             
  766.             if cookie.version == 0:
  767.                 if not erhn.endswith(domain) and not erhn.startswith('.') and not ('.' + erhn).endswith(domain):
  768.                     _debug('   effective request-host %s (even with added initial dot) does not end end with %s', erhn, domain)
  769.                     return False
  770.                 
  771.             
  772.             if cookie.version > 0 or self.strict_ns_domain & self.DomainRFC2965Match:
  773.                 if not domain_match(erhn, domain):
  774.                     _debug('   effective request-host %s does not domain-match %s', erhn, domain)
  775.                     return False
  776.                 
  777.             
  778.             if cookie.version > 0 or self.strict_ns_domain & self.DomainStrictNoDots:
  779.                 host_prefix = req_host[:-len(domain)]
  780.                 if host_prefix.find('.') >= 0 and not IPV4_RE.search(req_host):
  781.                     _debug('   host prefix %s for domain %s contains a dot', host_prefix, domain)
  782.                     return False
  783.                 
  784.             
  785.         
  786.         return True
  787.  
  788.     
  789.     def set_ok_port(self, cookie, request):
  790.         if cookie.port_specified:
  791.             req_port = request_port(request)
  792.             if req_port is None:
  793.                 req_port = '80'
  794.             else:
  795.                 req_port = str(req_port)
  796.             for p in cookie.port.split(','):
  797.                 
  798.                 try:
  799.                     int(p)
  800.                 except ValueError:
  801.                     _debug('   bad port %s (not numeric)', p)
  802.                     return False
  803.  
  804.                 if p == req_port:
  805.                     break
  806.                     continue
  807.             else:
  808.                 return False
  809.         
  810.         return True
  811.  
  812.     
  813.     def return_ok(self, cookie, request):
  814.         _debug(' - checking cookie %s=%s', cookie.name, cookie.value)
  815.         for n in ('version', 'verifiability', 'secure', 'expires', 'port', 'domain'):
  816.             fn_name = 'return_ok_' + n
  817.             fn = getattr(self, fn_name)
  818.             if not fn(cookie, request):
  819.                 return False
  820.                 continue
  821.         
  822.         return True
  823.  
  824.     
  825.     def return_ok_version(self, cookie, request):
  826.         if cookie.version > 0 and not (self.rfc2965):
  827.             _debug('   RFC 2965 cookies are switched off')
  828.             return False
  829.         elif cookie.version == 0 and not (self.netscape):
  830.             _debug('   Netscape cookies are switched off')
  831.             return False
  832.         
  833.         return True
  834.  
  835.     
  836.     def return_ok_verifiability(self, cookie, request):
  837.         if request.is_unverifiable() and is_third_party(request):
  838.             if cookie.version > 0 and self.strict_rfc2965_unverifiable:
  839.                 _debug('   third-party RFC 2965 cookie during unverifiable transaction')
  840.                 return False
  841.             elif cookie.version == 0 and self.strict_ns_unverifiable:
  842.                 _debug('   third-party Netscape cookie during unverifiable transaction')
  843.                 return False
  844.             
  845.         
  846.         return True
  847.  
  848.     
  849.     def return_ok_secure(self, cookie, request):
  850.         if cookie.secure and request.get_type() != 'https':
  851.             _debug('   secure cookie with non-secure request')
  852.             return False
  853.         
  854.         return True
  855.  
  856.     
  857.     def return_ok_expires(self, cookie, request):
  858.         if cookie.is_expired(self._now):
  859.             _debug('   cookie expired')
  860.             return False
  861.         
  862.         return True
  863.  
  864.     
  865.     def return_ok_port(self, cookie, request):
  866.         if cookie.port:
  867.             req_port = request_port(request)
  868.             if req_port is None:
  869.                 req_port = '80'
  870.             
  871.             for p in cookie.port.split(','):
  872.                 if p == req_port:
  873.                     break
  874.                     continue
  875.             else:
  876.                 return False
  877.         
  878.         return True
  879.  
  880.     
  881.     def return_ok_domain(self, cookie, request):
  882.         (req_host, erhn) = eff_request_host(request)
  883.         domain = cookie.domain
  884.         if cookie.version == 0 and self.strict_ns_domain & self.DomainStrictNonDomain and not (cookie.domain_specified) and domain != erhn:
  885.             _debug('   cookie with unspecified domain does not string-compare equal to request domain')
  886.             return False
  887.         
  888.         if cookie.version > 0 and not domain_match(erhn, domain):
  889.             _debug('   effective request-host name %s does not domain-match RFC 2965 cookie domain %s', erhn, domain)
  890.             return False
  891.         
  892.         if cookie.version == 0 and not ('.' + erhn).endswith(domain):
  893.             _debug('   request-host %s does not match Netscape cookie domain %s', req_host, domain)
  894.             return False
  895.         
  896.         return True
  897.  
  898.     
  899.     def domain_return_ok(self, domain, request):
  900.         (req_host, erhn) = eff_request_host(request)
  901.         if not req_host.startswith('.'):
  902.             req_host = '.' + req_host
  903.         
  904.         if not erhn.startswith('.'):
  905.             erhn = '.' + erhn
  906.         
  907.         if not req_host.endswith(domain) or erhn.endswith(domain):
  908.             return False
  909.         
  910.         if self.is_blocked(domain):
  911.             _debug('   domain %s is in user block-list', domain)
  912.             return False
  913.         
  914.         if self.is_not_allowed(domain):
  915.             _debug('   domain %s is not in user allow-list', domain)
  916.             return False
  917.         
  918.         return True
  919.  
  920.     
  921.     def path_return_ok(self, path, request):
  922.         _debug('- checking cookie path=%s', path)
  923.         req_path = request_path(request)
  924.         if not req_path.startswith(path):
  925.             _debug('  %s does not path-match %s', req_path, path)
  926.             return False
  927.         
  928.         return True
  929.  
  930.  
  931.  
  932. def vals_sorted_by_key(adict):
  933.     keys = adict.keys()
  934.     keys.sort()
  935.     return map(adict.get, keys)
  936.  
  937.  
  938. def deepvalues(mapping):
  939.     values = vals_sorted_by_key(mapping)
  940.     for obj in values:
  941.         mapping = False
  942.         
  943.         try:
  944.             obj.items
  945.         except AttributeError:
  946.             pass
  947.  
  948.         mapping = True
  949.         for subobj in deepvalues(obj):
  950.             yield subobj
  951.         
  952.         if not mapping:
  953.             yield obj
  954.             continue
  955.     
  956.  
  957.  
  958. class Absent:
  959.     pass
  960.  
  961.  
  962. class CookieJar:
  963.     non_word_re = re.compile('\\W')
  964.     quote_re = re.compile('([\\"\\\\])')
  965.     strict_domain_re = re.compile('\\.?[^.]*')
  966.     domain_re = re.compile('[^.]*')
  967.     dots_re = re.compile('^\\.+')
  968.     magic_re = '^\\#LWP-Cookies-(\\d+\\.\\d+)'
  969.     
  970.     def __init__(self, policy = None):
  971.         if policy is None:
  972.             policy = DefaultCookiePolicy()
  973.         
  974.         self._policy = policy
  975.         self._cookies_lock = _threading.RLock()
  976.         self._cookies = { }
  977.  
  978.     
  979.     def set_policy(self, policy):
  980.         self._policy = policy
  981.  
  982.     
  983.     def _cookies_for_domain(self, domain, request):
  984.         cookies = []
  985.         if not self._policy.domain_return_ok(domain, request):
  986.             return []
  987.         
  988.         _debug('Checking %s for cookies to return', domain)
  989.         cookies_by_path = self._cookies[domain]
  990.         for path in cookies_by_path.keys():
  991.             if not self._policy.path_return_ok(path, request):
  992.                 continue
  993.             
  994.             cookies_by_name = cookies_by_path[path]
  995.             for cookie in cookies_by_name.values():
  996.                 if not self._policy.return_ok(cookie, request):
  997.                     _debug('   not returning cookie')
  998.                     continue
  999.                 
  1000.                 _debug("   it's a match")
  1001.                 cookies.append(cookie)
  1002.             
  1003.         
  1004.         return cookies
  1005.  
  1006.     
  1007.     def _cookies_for_request(self, request):
  1008.         cookies = []
  1009.         for domain in self._cookies.keys():
  1010.             cookies.extend(self._cookies_for_domain(domain, request))
  1011.         
  1012.         return cookies
  1013.  
  1014.     
  1015.     def _cookie_attrs(self, cookies):
  1016.         
  1017.         def decreasing_size(a, b):
  1018.             return cmp(len(b.path), len(a.path))
  1019.  
  1020.         cookies.sort(decreasing_size)
  1021.         version_set = False
  1022.         attrs = []
  1023.         for cookie in cookies:
  1024.             version = cookie.version
  1025.             if not version_set:
  1026.                 version_set = True
  1027.                 if version > 0:
  1028.                     attrs.append('$Version=%s' % version)
  1029.                 
  1030.             
  1031.             if cookie.value is not None and self.non_word_re.search(cookie.value) and version > 0:
  1032.                 value = self.quote_re.sub('\\\\\\1', cookie.value)
  1033.             else:
  1034.                 value = cookie.value
  1035.             if cookie.value is None:
  1036.                 attrs.append(cookie.name)
  1037.             else:
  1038.                 attrs.append('%s=%s' % (cookie.name, value))
  1039.             if version > 0:
  1040.                 if cookie.path_specified:
  1041.                     attrs.append('$Path="%s"' % cookie.path)
  1042.                 
  1043.                 if cookie.domain.startswith('.'):
  1044.                     domain = cookie.domain
  1045.                     if not (cookie.domain_initial_dot) and domain.startswith('.'):
  1046.                         domain = domain[1:]
  1047.                     
  1048.                     attrs.append('$Domain="%s"' % domain)
  1049.                 
  1050.                 if cookie.port is not None:
  1051.                     p = '$Port'
  1052.                     if cookie.port_specified:
  1053.                         p = p + '="%s"' % cookie.port
  1054.                     
  1055.                     attrs.append(p)
  1056.                 
  1057.             cookie.port is not None
  1058.         
  1059.         return attrs
  1060.  
  1061.     
  1062.     def add_cookie_header(self, request):
  1063.         _debug('add_cookie_header')
  1064.         self._cookies_lock.acquire()
  1065.         self._policy._now = self._now = int(time.time())
  1066.         cookies = self._cookies_for_request(request)
  1067.         attrs = self._cookie_attrs(cookies)
  1068.         if attrs:
  1069.             if not request.has_header('Cookie'):
  1070.                 request.add_unredirected_header('Cookie', '; '.join(attrs))
  1071.             
  1072.         
  1073.         if self._policy.rfc2965 and not (self._policy.hide_cookie2) and not request.has_header('Cookie2'):
  1074.             for cookie in cookies:
  1075.                 if cookie.version != 1:
  1076.                     request.add_unredirected_header('Cookie2', '$Version="1"')
  1077.                     break
  1078.                     continue
  1079.             
  1080.         
  1081.         self._cookies_lock.release()
  1082.         self.clear_expired_cookies()
  1083.  
  1084.     
  1085.     def _normalized_cookie_tuples(self, attrs_set):
  1086.         cookie_tuples = []
  1087.         boolean_attrs = ('discard', 'secure')
  1088.         value_attrs = ('version', 'expires', 'max-age', 'domain', 'path', 'port', 'comment', 'commenturl')
  1089.         for cookie_attrs in attrs_set:
  1090.             (name, value) = cookie_attrs[0]
  1091.             max_age_set = False
  1092.             bad_cookie = False
  1093.             standard = { }
  1094.             rest = { }
  1095.             for k, v in cookie_attrs[1:]:
  1096.                 lc = k.lower()
  1097.                 if lc in value_attrs or lc in boolean_attrs:
  1098.                     k = lc
  1099.                 
  1100.                 if k in boolean_attrs and v is None:
  1101.                     v = True
  1102.                 
  1103.                 if k in standard:
  1104.                     continue
  1105.                 
  1106.                 if k == 'domain':
  1107.                     if v is None:
  1108.                         _debug('   missing value for domain attribute')
  1109.                         bad_cookie = True
  1110.                         break
  1111.                     
  1112.                     v = v.lower()
  1113.                 
  1114.                 if k == 'expires':
  1115.                     if max_age_set:
  1116.                         continue
  1117.                     
  1118.                     if v is None:
  1119.                         _debug('   missing or invalid value for expires attribute: treating as session cookie')
  1120.                         continue
  1121.                     
  1122.                 
  1123.                 if k == 'max-age':
  1124.                     max_age_set = True
  1125.                     
  1126.                     try:
  1127.                         v = int(v)
  1128.                     except ValueError:
  1129.                         _debug('   missing or invalid (non-numeric) value for max-age attribute')
  1130.                         bad_cookie = True
  1131.                         break
  1132.  
  1133.                     k = 'expires'
  1134.                     v = self._now + v
  1135.                 
  1136.                 if k in value_attrs or k in boolean_attrs:
  1137.                     if v is None and k not in ('port', 'comment', 'commenturl'):
  1138.                         _debug('   missing value for %s attribute' % k)
  1139.                         bad_cookie = True
  1140.                         break
  1141.                     
  1142.                     standard[k] = v
  1143.                     continue
  1144.                 rest[k] = v
  1145.             
  1146.             if bad_cookie:
  1147.                 continue
  1148.             
  1149.             cookie_tuples.append((name, value, standard, rest))
  1150.         
  1151.         return cookie_tuples
  1152.  
  1153.     
  1154.     def _cookie_from_cookie_tuple(self, tup, request):
  1155.         (name, value, standard, rest) = tup
  1156.         domain = standard.get('domain', Absent)
  1157.         path = standard.get('path', Absent)
  1158.         port = standard.get('port', Absent)
  1159.         expires = standard.get('expires', Absent)
  1160.         version = standard.get('version', None)
  1161.         if version is not None:
  1162.             version = int(version)
  1163.         
  1164.         secure = standard.get('secure', False)
  1165.         discard = standard.get('discard', False)
  1166.         comment = standard.get('comment', None)
  1167.         comment_url = standard.get('commenturl', None)
  1168.         if path is not Absent and path != '':
  1169.             path_specified = True
  1170.             path = escape_path(path)
  1171.         else:
  1172.             path_specified = False
  1173.             path = request_path(request)
  1174.             i = path.rfind('/')
  1175.             if i != -1:
  1176.                 if version == 0:
  1177.                     path = path[:i]
  1178.                 else:
  1179.                     path = path[:i + 1]
  1180.             
  1181.             if len(path) == 0:
  1182.                 path = '/'
  1183.             
  1184.         domain_specified = domain is not Absent
  1185.         domain_initial_dot = False
  1186.         if domain_specified:
  1187.             domain_initial_dot = bool(domain.startswith('.'))
  1188.         
  1189.         if domain is Absent:
  1190.             (req_host, erhn) = eff_request_host(request)
  1191.             domain = erhn
  1192.         elif not domain.startswith('.'):
  1193.             domain = '.' + domain
  1194.         
  1195.         port_specified = False
  1196.         if port is not Absent:
  1197.             if port is None:
  1198.                 port = request_port(request)
  1199.             else:
  1200.                 port_specified = True
  1201.                 port = re.sub('\\s+', '', port)
  1202.         else:
  1203.             port = None
  1204.         if expires is Absent:
  1205.             expires = None
  1206.             discard = True
  1207.         elif expires <= self._now:
  1208.             
  1209.             try:
  1210.                 self.clear(domain, path, name)
  1211.             except KeyError:
  1212.                 pass
  1213.  
  1214.             _debug("Expiring cookie, domain='%s', path='%s', name='%s'", domain, path, name)
  1215.             return None
  1216.         
  1217.         return Cookie(version, name, value, port, port_specified, domain, domain_specified, domain_initial_dot, path, path_specified, secure, expires, discard, comment, comment_url, rest)
  1218.  
  1219.     
  1220.     def _cookies_from_attrs_set(self, attrs_set, request):
  1221.         cookie_tuples = self._normalized_cookie_tuples(attrs_set)
  1222.         cookies = []
  1223.         for tup in cookie_tuples:
  1224.             cookie = self._cookie_from_cookie_tuple(tup, request)
  1225.             if cookie:
  1226.                 cookies.append(cookie)
  1227.                 continue
  1228.         
  1229.         return cookies
  1230.  
  1231.     
  1232.     def _process_rfc2109_cookies(self, cookies):
  1233.         rfc2109_as_ns = getattr(self._policy, 'rfc2109_as_netscape', None)
  1234.         if rfc2109_as_ns is None:
  1235.             rfc2109_as_ns = not (self._policy.rfc2965)
  1236.         
  1237.         for cookie in cookies:
  1238.             if cookie.version == 1:
  1239.                 cookie.rfc2109 = True
  1240.                 if rfc2109_as_ns:
  1241.                     cookie.version = 0
  1242.                 
  1243.             rfc2109_as_ns
  1244.         
  1245.  
  1246.     
  1247.     def make_cookies(self, response, request):
  1248.         headers = response.info()
  1249.         rfc2965_hdrs = headers.getheaders('Set-Cookie2')
  1250.         ns_hdrs = headers.getheaders('Set-Cookie')
  1251.         rfc2965 = self._policy.rfc2965
  1252.         netscape = self._policy.netscape
  1253.         if not not rfc2965_hdrs or not ns_hdrs:
  1254.             if not not ns_hdrs or not rfc2965:
  1255.                 if (not rfc2965_hdrs or not netscape or not netscape) and not rfc2965:
  1256.                     return []
  1257.                 
  1258.         
  1259.         try:
  1260.             cookies = self._cookies_from_attrs_set(split_header_words(rfc2965_hdrs), request)
  1261.         except Exception:
  1262.             _warn_unhandled_exception()
  1263.             cookies = []
  1264.  
  1265.         if ns_hdrs and netscape:
  1266.             
  1267.             try:
  1268.                 ns_cookies = self._cookies_from_attrs_set(parse_ns_headers(ns_hdrs), request)
  1269.             except Exception:
  1270.                 _warn_unhandled_exception()
  1271.                 ns_cookies = []
  1272.  
  1273.             self._process_rfc2109_cookies(ns_cookies)
  1274.             if rfc2965:
  1275.                 lookup = { }
  1276.                 for cookie in cookies:
  1277.                     lookup[(cookie.domain, cookie.path, cookie.name)] = None
  1278.                 
  1279.                 
  1280.                 def no_matching_rfc2965(ns_cookie, lookup = lookup):
  1281.                     key = (ns_cookie.domain, ns_cookie.path, ns_cookie.name)
  1282.                     return key not in lookup
  1283.  
  1284.                 ns_cookies = filter(no_matching_rfc2965, ns_cookies)
  1285.             
  1286.             if ns_cookies:
  1287.                 cookies.extend(ns_cookies)
  1288.             
  1289.         
  1290.         return cookies
  1291.  
  1292.     
  1293.     def set_cookie_if_ok(self, cookie, request):
  1294.         self._cookies_lock.acquire()
  1295.         self._policy._now = self._now = int(time.time())
  1296.         if self._policy.set_ok(cookie, request):
  1297.             self.set_cookie(cookie)
  1298.         
  1299.         self._cookies_lock.release()
  1300.  
  1301.     
  1302.     def set_cookie(self, cookie):
  1303.         c = self._cookies
  1304.         self._cookies_lock.acquire()
  1305.         
  1306.         try:
  1307.             if cookie.domain not in c:
  1308.                 c[cookie.domain] = { }
  1309.             
  1310.             c2 = c[cookie.domain]
  1311.             if cookie.path not in c2:
  1312.                 c2[cookie.path] = { }
  1313.             
  1314.             c3 = c2[cookie.path]
  1315.             c3[cookie.name] = cookie
  1316.         finally:
  1317.             self._cookies_lock.release()
  1318.  
  1319.  
  1320.     
  1321.     def extract_cookies(self, response, request):
  1322.         _debug('extract_cookies: %s', response.info())
  1323.         self._cookies_lock.acquire()
  1324.         self._policy._now = self._now = int(time.time())
  1325.         for cookie in self.make_cookies(response, request):
  1326.             if self._policy.set_ok(cookie, request):
  1327.                 _debug(' setting cookie: %s', cookie)
  1328.                 self.set_cookie(cookie)
  1329.                 continue
  1330.         
  1331.         self._cookies_lock.release()
  1332.  
  1333.     
  1334.     def clear(self, domain = None, path = None, name = None):
  1335.         if name is not None:
  1336.             if domain is None or path is None:
  1337.                 raise ValueError('domain and path must be given to remove a cookie by name')
  1338.             
  1339.             del self._cookies[domain][path][name]
  1340.         elif path is not None:
  1341.             if domain is None:
  1342.                 raise ValueError('domain must be given to remove cookies by path')
  1343.             
  1344.             del self._cookies[domain][path]
  1345.         elif domain is not None:
  1346.             del self._cookies[domain]
  1347.         else:
  1348.             self._cookies = { }
  1349.  
  1350.     
  1351.     def clear_session_cookies(self):
  1352.         self._cookies_lock.acquire()
  1353.         for cookie in self:
  1354.             if cookie.discard:
  1355.                 self.clear(cookie.domain, cookie.path, cookie.name)
  1356.                 continue
  1357.         
  1358.         self._cookies_lock.release()
  1359.  
  1360.     
  1361.     def clear_expired_cookies(self):
  1362.         self._cookies_lock.acquire()
  1363.         now = time.time()
  1364.         for cookie in self:
  1365.             if cookie.is_expired(now):
  1366.                 self.clear(cookie.domain, cookie.path, cookie.name)
  1367.                 continue
  1368.         
  1369.         self._cookies_lock.release()
  1370.  
  1371.     
  1372.     def __iter__(self):
  1373.         return deepvalues(self._cookies)
  1374.  
  1375.     
  1376.     def __len__(self):
  1377.         i = 0
  1378.         for cookie in self:
  1379.             i = i + 1
  1380.         
  1381.         return i
  1382.  
  1383.     
  1384.     def __repr__(self):
  1385.         r = []
  1386.         for cookie in self:
  1387.             r.append(repr(cookie))
  1388.         
  1389.         return '<%s[%s]>' % (self.__class__, ', '.join(r))
  1390.  
  1391.     
  1392.     def __str__(self):
  1393.         r = []
  1394.         for cookie in self:
  1395.             r.append(str(cookie))
  1396.         
  1397.         return '<%s[%s]>' % (self.__class__, ', '.join(r))
  1398.  
  1399.  
  1400.  
  1401. class LoadError(IOError):
  1402.     pass
  1403.  
  1404.  
  1405. class FileCookieJar(CookieJar):
  1406.     
  1407.     def __init__(self, filename = None, delayload = False, policy = None):
  1408.         CookieJar.__init__(self, policy)
  1409.         if filename is not None:
  1410.             
  1411.             try:
  1412.                 filename + ''
  1413.             raise ValueError('filename must be string-like')
  1414.  
  1415.         
  1416.         self.filename = filename
  1417.         self.delayload = bool(delayload)
  1418.  
  1419.     
  1420.     def save(self, filename = None, ignore_discard = False, ignore_expires = False):
  1421.         raise NotImplementedError()
  1422.  
  1423.     
  1424.     def load(self, filename = None, ignore_discard = False, ignore_expires = False):
  1425.         if filename is None:
  1426.             if self.filename is not None:
  1427.                 filename = self.filename
  1428.             else:
  1429.                 raise ValueError(MISSING_FILENAME_TEXT)
  1430.         
  1431.         f = open(filename)
  1432.         
  1433.         try:
  1434.             self._really_load(f, filename, ignore_discard, ignore_expires)
  1435.         finally:
  1436.             f.close()
  1437.  
  1438.  
  1439.     
  1440.     def revert(self, filename = None, ignore_discard = False, ignore_expires = False):
  1441.         if filename is None:
  1442.             if self.filename is not None:
  1443.                 filename = self.filename
  1444.             else:
  1445.                 raise ValueError(MISSING_FILENAME_TEXT)
  1446.         
  1447.         self._cookies_lock.acquire()
  1448.         old_state = copy.deepcopy(self._cookies)
  1449.         self._cookies = { }
  1450.         
  1451.         try:
  1452.             self.load(filename, ignore_discard, ignore_expires)
  1453.         except (LoadError, IOError):
  1454.             self._cookies = old_state
  1455.             raise 
  1456.  
  1457.         self._cookies_lock.release()
  1458.  
  1459.  
  1460. from _LWPCookieJar import LWPCookieJar, lwp_cookie_str
  1461. from _MozillaCookieJar import MozillaCookieJar
  1462.